package com.cfweb.api;

import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.cfweb.controller.LoginHandler;
import com.cfweb.exception.CloudFoundryApiException;
import com.cfweb.util.CloudFoundryClientUtil;
import com.cfweb.util.HttpStatusUtil;
import com.cfweb.util.JsonUtil;
import com.cfweb.util.StringUtil;

public class UserApi {

	static Logger logger = Logger.getLogger(UserApi.class);

	static Map<String, String> roleMap = new HashMap<String, String>();

	static {
		roleMap.put("OrgManager", "managers");
		roleMap.put("BillingManager", "billing_managers");
		roleMap.put("OrgAuditor", "auditors");
		roleMap.put("SpaceManager", "managers");
		roleMap.put("SpaceDeveloper", "developers");
		roleMap.put("SpaceAuditor", "auditors");
	}

	/**
	 * create a new user
	 * 
	 * @param session
	 * @param userName
	 * @param password
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean create_user(HttpSession session, final String userName, final String password)
			throws Exception {
		HttpClient httpClient = null;
		HttpPost httpPost = null;
		String userId;
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = "http://uaa" + host.substring(10) + "/Users";

			httpClient = new DefaultHttpClient();
			httpPost = new HttpPost(urlPath);
			CloudFoundryClientUtil.setUuaHeaders(httpPost, session);
			String tmp = "{\"userName\":\"" + userName + "\",\"emails\":[{\"value\":\"" + userName
					+ "\"}],\"password\":\"" + password + "\",\"name\":{\"givenName\":\"" + userName
					+ "\",\"familyName\":\"" + userName + "\"}}";
			HttpEntity postEntity = new StringEntity(tmp, "UTF-8");
			httpPost.setEntity(postEntity);
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			String content = EntityUtils.toString(entity, "UTF-8");
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())
					&& response.getStatusLine().getStatusCode() != 200) {
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()),
						(String) data.get("message"));
			}
			userId = (String) data.get("id");
			// String content = EntityUtils.toString(returnEntity, "UTF-8");
		} catch (Exception e) {
			throw e;
		} finally {
			httpPost.abort();
			httpClient.getConnectionManager().shutdown();
		}

		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/users";

			httpClient = new DefaultHttpClient();
			httpPost = new HttpPost(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPost, session);
			String tmp = "{\"guid\":\"" + userId + "\"}";
			HttpEntity postEntity = new StringEntity(tmp, "UTF-8");
			httpPost.setEntity(postEntity);
			HttpResponse response = httpClient.execute(httpPost);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				String content = EntityUtils.toString(response.getEntity(), "UTF-8");
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()),
						(String) data.get("message"));
			}
			// String content = EntityUtils.toString(returnEntity, "UTF-8");
		} catch (Exception e) {
			delete_cc_user(session, userName);
			throw e;
		} finally {
			httpPost.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return true;
	}

	/**
	 * delete a user
	 * 
	 * @param session
	 * @param userName
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean delete_user(HttpSession session, String userName) throws Exception {
		HttpClient httpClient = null;
		HttpDelete httpDelete = null;
		String userId;
		userId = get_user_id(session, userName);
		if (userId.isEmpty()) {
			return false;
		}
		delete_cc_user(session, userName);
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = "http://uaa" + host.substring(10) + "/Users/" + userId;

			httpClient = new DefaultHttpClient();
			httpDelete = new HttpDelete(urlPath);
			CloudFoundryClientUtil.setUuaHeaders(httpDelete, session);
			HttpResponse response = httpClient.execute(httpDelete);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				String content = EntityUtils.toString(response.getEntity(), "UTF-8");
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()),
						(String) data.get("message"));
			}
		} catch (Exception e) {
			throw e;
		} finally {
			httpDelete.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return true;
	}

	/**
	 * delete a user of cc
	 * 
	 * @param session
	 * @param userName
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean delete_cc_user(HttpSession session, String userName) throws Exception {
		HttpClient httpClient = null;
		HttpDelete httpDelete = null;
		String userId;
		userId = get_user_id(session, userName);
		if (userId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/users/" + userId + "?async=false";

			httpClient = new DefaultHttpClient();
			httpDelete = new HttpDelete(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpDelete, session);
			HttpResponse response = httpClient.execute(httpDelete);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();
				String content = EntityUtils.toString(entity, "UTF-8");
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
		} catch (Exception e) {
			throw e;
		} finally {
			httpDelete.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return true;
	}

	/**
	 * set roles of the user in the org
	 * 
	 * @param session
	 * @param userName
	 * @param orgName
	 * @param roleType
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean set_org_role(HttpSession session, String userName, String orgName, String roleType)
			throws Exception {
		HttpClient httpClient = null;
		HttpPut httpPut = null;
		String userId;
		String orgId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/organizations/" + orgId + "/" + roleMap.get(roleType) + "/" + userId;

			httpClient = new DefaultHttpClient();
			httpPut = new HttpPut(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPut, session);
			HttpResponse response = httpClient.execute(httpPut);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();
				String content = EntityUtils.toString(entity, "UTF-8");
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
			add_into_org(session, userName, orgName);
		} catch (Exception e) {
			throw e;
		} finally {
			httpPut.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return true;
	}

	/**
	 * unset roles of the user in the org
	 * 
	 * @param session
	 * @param userName
	 * @param orgName
	 * @param roleType
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean unset_org_role(HttpSession session, String userName, String orgName, String roleType)
			throws Exception {
		String userId;
		String orgId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/organizations/" + orgId + "/" + roleMap.get(roleType) + "/" + userId;
			CloudFoundryClientUtil.doCCDelete(urlPath, null, session);
		} catch (Exception e) {
			throw e;
		}
		return true;
	}

	/**
	 * set roles of the user of the space in a org
	 * 
	 * @param session
	 * @param userName
	 * @param orgName
	 * @param roleType
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean set_space_role(HttpSession session, String userName, String orgName, String spaceName,
			String roleType) throws Exception {
		HttpClient httpClient = null;
		HttpPut httpPut = null;
		String userId;
		String orgId;
		String spaceId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		spaceId = get_space_id(session, orgName, spaceName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		if (StringUtil.isEmpty(spaceId)) {
			return false;
		}
		if (!add_into_org(session, userName, orgName)) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/spaces/" + spaceId + "/" + roleMap.get(roleType) + "/" + userId;

			httpClient = new DefaultHttpClient();
			httpPut = new HttpPut(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPut, session);
			HttpResponse response = httpClient.execute(httpPut);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();
				String content = EntityUtils.toString(entity, "UTF-8");
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
		} catch (Exception e) {
			throw e;
		} finally {
			httpPut.abort();
			httpClient.getConnectionManager().shutdown();
		}

		return true;
	}

	/**
	 * unset roles of the user of the space in a org
	 * 
	 * @param session
	 * @param userName
	 * @param orgName
	 * @param roleType
	 * @return boolean
	 * @throws Exception
	 */
	public static boolean unset_space_role(HttpSession session, String userName, String orgName, String spaceName,
			String roleType) throws Exception {
		String userId;
		String orgId;
		String spaceId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		spaceId = get_space_id(session, orgName, spaceName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		if (StringUtil.isEmpty(spaceId)) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/spaces/" + spaceId + "/" + roleMap.get(roleType) + "/" + userId;
			CloudFoundryClientUtil.doCCDelete(urlPath, null, session);
		} catch (Exception e) {
			throw e;
		}

		return true;
	}

	/**
	 * add a user into org
	 * 
	 * @param session
	 * @param userName
	 * @param orgName
	 * @return boolean
	 * @throws Exception
	 */
	private static boolean add_into_org(HttpSession session, String userName, String orgName) throws Exception {
		HttpClient httpClient = null;
		HttpPut httpPut = null;
		String userId;
		String orgId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/organizations/" + orgId + "/users/" + userId;
			httpClient = new DefaultHttpClient();
			httpPut = new HttpPut(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPut, session);
			HttpResponse response = httpClient.execute(httpPut);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();
				String content = EntityUtils.toString(entity, "UTF-8");
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
		} catch (Exception e) {
			throw e;
		} finally {
			httpPut.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return true;
	}

	/**
	 * get id of a user
	 * 
	 * @param session
	 * @param userName
	 * @return userId
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String get_user_id(HttpSession session, String userName) throws Exception {
		HttpClient httpClient = null;
		HttpGet httpGet = null;
		String userId = null;
		String urlPath = null;
		if (userName.equals((String) session.getAttribute(LoginHandler.USERNAME))) {
			String object = (String) session.getAttribute(LoginHandler.USERID);
			if (object != null && object.equals("")) {
				userId = object;
			}

		}
		if (userId != null) {
			return userId;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			urlPath = "http://uaa" + host.substring(10) + "/Users?attributes=id,userName&filter=userName+Eq+%22"
					+ userName + "%22";
			// System.out.println(urlPath);
			httpClient = new DefaultHttpClient();
			httpGet = new HttpGet(urlPath);
			CloudFoundryClientUtil.setUuaHeaders(httpGet, session);
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			String content = EntityUtils.toString(entity, "UTF-8");
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()),
						(String) data.get("message"));
			}
			if ((int) data.get("totalResults") == 0) {
				return "";
			}
			userId = (String) ((Map<String, Object>) ((List) (data.get("resources"))).get(0)).get("id");
		} catch (Exception e) {
			throw e;
		} finally {
			httpGet.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return userId;
	}

	/**
	 * get id of a org
	 * 
	 * @param session
	 * @param orgName
	 * @return userId
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String get_org_id(HttpSession session, String orgName) throws Exception {
		HttpClient httpClient = null;
		HttpGet httpGet = null;
		String orgId;
		String urlPath = null;
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			urlPath = host + "/v2/organizations?q=name%3A" + orgName + "&inline-relations-depth=1";

			httpClient = new DefaultHttpClient();
			httpGet = new HttpGet(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpGet, session);
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			String content = EntityUtils.toString(entity, "UTF-8");
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
			// System.out.println(((Map<String, Object>)((Map<String,
			// Object>)((List)data.get("resources")).get(0)).get("metadata")).get("guid"));
			if ((int) data.get("total_results") == 0) {
				return "";
			}
			orgId = (String) ((Map<String, Object>) ((Map<String, Object>) ((List) data.get("resources")).get(0))
					.get("metadata")).get("guid");
		} catch (Exception e) {
			throw e;
		} finally {
			httpGet.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return orgId;
	}

	/**
	 * get id of a space
	 * 
	 * @param session
	 * @param orgName
	 * @param spaceName
	 * @return userId
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String get_space_id(HttpSession session, String orgName, String spaceName) throws Exception {
		HttpClient httpClient = null;
		HttpGet httpGet = null;
		String orgId = get_org_id(session, orgName);
		if (StringUtil.isEmpty(orgId)) {
			return "";
		}
		String spaceId;
		String urlPath = null;
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			urlPath = host + "/v2/organizations/" + orgId + "/spaces?q=name%3A" + spaceName
					+ "&inline-relations-depth=1";

			httpClient = new DefaultHttpClient();
			httpGet = new HttpGet(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpGet, session);
			/**
			 * excute
			 */
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			String content = EntityUtils.toString(entity, "UTF-8");
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
			if ((int) data.get("total_results") == 0) {
				return "";
			}
			spaceId = (String) ((Map<String, Object>) ((Map<String, Object>) ((List) data.get("resources")).get(0))
					.get("metadata")).get("guid");
		} catch (Exception e) {
			throw e;
		} finally {
			httpGet.abort();
			httpClient.getConnectionManager().shutdown();
		}
		return spaceId;
	}

	public static void updateUserPassword(HttpSession session, String uid, Map<String, Object> params)
			throws Exception {
		String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
		String url = "http://uaa" + host.substring(10) + "/Users/" + uid + "/password";
		CloudFoundryClientUtil.doUaaPut(url, params, session);
	}

	public static void main(String[] args) {
		Map<String, Object> object = new HashMap<>();
		object.put("password", "123");
		object.put("oldPassword", "12345");
		// List<String> schemas=new ArrayList<>();
		// schemas.add("urn:scim:schemas:core:1.0");
		// object.put("schemas", schemas);
		try {
			updateUserPassword(null, "02cf91c3-fce7-441e-a410-6aef5d7e6a55", object);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
